#include <Arduino.h>
#include "CircularBuffer.h"
#include "I2CSlave.h"
#include "SWMonitor.h"

#include "DataStorage.h"
#include "DataStorageIO.h"

#include "SmartBox.h"

#include "DigitalOut.h"
#include "log.h"
#include "lwmp.h"
#include "DispatcherHandler.h"
#include "module_general_reg.h"
#include <AnalogPort.h>
#include <DigitalPort.h>
#include <SN74AHC595.h>
#include "IOPort.h"
#include "IOReader.h"
// put function declarations here:
//"PD3",TIMER2B);
//"PB2",TIMER1B);
//"PD5",TIMER0B);
//"PB1",TIMER1A);
//"PB3",TIMER2A);
// CmdLine cmdline;

Mail<> mb;

I2CSlave i2c_slave(mb);

DataStorageIO io_data(mb);

DataStorage dataStorage(&io_data);

SW1248 sw1248;

SWMonitor sw_monitor(sw1248);

AnalogPort  aio_port(PC_0,PC_1,PC_2,PC_3);
DigitalPort dio_port(PD_3,PB_1,PB_2,PB_3);
IOPort ioport(dio_port,aio_port);

IOReader ioReader(ioport);

ti::SN74AHC595 sn74ahc595(PD_6,PD_2,PD_5,PD_4);

DispatcherHandler dispatcherHandler(ioport,sn74ahc595,dataStorage,PB_5);

SmartBox smb(i2c_slave,dispatcherHandler,mb);

Scheduler* scheduler_tasks[]={
  //&cmdline,           //添加任务0: 接收命令         (Y)
  &sw1248,              //添加任务1: 按键扫描         (Y)
  &sw_monitor,          //添加任务2: 按键状态检测     (Y)
  &ioReader,            //添加任务3: 定时读取IO       (Y)
  &dataStorage,         //添加任务4: 数据检查         (Y)
  &dispatcherHandler,   //添加任务5: 执行控制         (Y)
  &smb                  //添加任务6: 系统控制         (Y)
};

void setup() {

  // put your setup code here, to run once:

  // start serial for output 
  Serial.begin(9600);    
  log::debug("pro:WF1-IO_Expander@%s-%s\r\n",__DATE__,__TIME__);


  // start sw1248 
  sw1248.begin();
  log::debug("sw1248 begin:0x%x\r\n",sw1248.state().value);
  sw_monitor.attach([]{
    i2c_slave.begin(sw1248.state().value);
    log::debug("i2c begin new addr:%x\r\n",sw1248.state().value);
  });
  

  // start data storage 
  dataStorage.begin();
  log::debug("ds begin:0x%x\r\n",dataStorage.read_data_storage_eof());

  // start i2c
  i2c_slave.begin(sw1248.state().value);
  log::debug("i2c begin:%x\r\n",sw1248.state().value);

  
  i2c_slave.on_request([]{
    //返回主机请求的数据
    data_storage_reg_read_t& reg = dispatcherHandler.get_reg_data(i2c_slave.get_reg_read_address());
    i2c_slave.write((const uint8_t *)reg.data,reg.size);
  });

  i2c_slave.on_receive([](int howMany){
    //处理主机发送的数据
      i2c_slave.handle_on_receive(howMany,dataStorage.module_header_reg().module_name);
      dataStorage.update();
  });

  smb.begin();
  log::debug("run tasks\r\n");
}

void loop() {
  // put your main code here, to run repeatedly:
  for(uint8_t i=0;i<sizeof(scheduler_tasks)/sizeof(Scheduler*);i++){
    scheduler_tasks[i]->schedule();
  }
}

void serialEvent() {
  // 当接收到数据时，这个函数会被自动调用
  // cmdline.cleanup();
  // while (Serial.available()) {
  //   char inChar = (char)Serial.read(); // 读取一个字节的数据
  //   cmdline.append(inChar);
  // }
  // cmdline.update();
}